package afox.mvn.plugin.jy;

/*
 * Copyright 2011-2013 Alexander Fox <alex7fox@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Map;

import org.python.core.Py;
import org.python.core.PySystemState;
import org.python.util.PythonInterpreter;

public class JyScript {
    private PythonInterpreter engine = null;

    public JyScript() {
        init(null);
    }

    public JyScript(String[] pathEntries) {
        init(pathEntries);
    }

    private void init(String[] pathEntries) {
        PySystemState engineSys = new PySystemState();
        if (pathEntries != null) {
            for (String pathEntry : pathEntries) {
                engineSys.path.append(Py.newString(pathEntry));
            }
        }
        Py.setSystemState(engineSys);
        this.engine = new PythonInterpreter();
    }

    public Object eval(Object script, Map<String, Object> bindings) throws IllegalArgumentException {
        if (bindings != null) {
            for (String key : bindings.keySet()) {
                this.engine.set(key, bindings.get(key));
            }
        }
        if (script instanceof InputStream) {
            this.engine.execfile((InputStream) script);
        } else if (script instanceof String) {
            this.engine.exec((String) script);
        } else {
            throw new IllegalArgumentException("Script object not supported " + script);
        }
        return get("g_returnvalue");
    }

    public Object eval(Object script) {
        return eval(script, null);
    }

    public Object get(String variableName) {
        return this.engine.get(variableName);
    }

    private static void printUsage() {
        System.err.println("Usage: java afox.py.JyScript [-c|-f|-m] [file|command|module]");
        System.err.println("  -c command");
        System.err.println("  -f file");
        System.err.println("  -m python module (in classpath)");
    }

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            for (String i : args)
                System.out.print(" " + i);
            System.out.println();
            System.err.println("Wrong number of arguments: " + args.length);
            printUsage();
            System.exit(1);
        } else if ("-c".equals(args[0])) {
            if (args.length != 2) {
                System.err.println("Command required");
                printUsage();
                System.exit(1);
            }
            JyScript j = new JyScript();
            System.out.println(j.eval(args[1]));
        } else if ("-f".equals(args[0])) {
            File f = new File(args[1]);
            FileReader r = null;
            try {
                r = new FileReader(f);
            } catch (FileNotFoundException e) {
                System.err.println("File not found");
                System.exit(1);
            }
            JyScript j = new JyScript();
            System.out.println(j.eval(r));
        } else if ("-m".equals(args[0])) {
            String module = args[1];
            ClassLoader loader = ClassLoader.getSystemClassLoader();
            URL url = loader.getResource(module);
            if (url == null)
                throw new RuntimeException(String.format("Cannot find module: %s", module));
            InputStream in = url.openStream();
            Reader r = new InputStreamReader(in);
            JyScript j = new JyScript();
            j.eval(r);
        }
    }
}
